# _*_ coding: utf-8 _*_
"""
@ 时间    ：2024/10/22 20:37
@ 作者    ：旺财
@ 文件    ：02 调优模型.py
@ 说明    ：对01中原工离职预测模型进行调优：通过GridSearch网格搜索与K折交叉验证调优
"""
import pandas as pd
from matplotlib import pyplot as plt
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import roc_auc_score, roc_curve

# 1.读取数据
df = pd.read_excel('员工离职预测模型.xlsx')
print(df.head())

# 2.提取特征变量与目标变量
df['工资'] = df['工资'].map({'低': 0, '中': 1, '高': 2}).astype(int)
x = df.drop(columns='离职')
y = df['离职']

# 3.划分训练集和测试集数据,其中test_size=0.2
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=11)

# 4.决策树模型-原始
mode = DecisionTreeClassifier(max_depth=3)
mode.fit(x_train, y_train)

# 5.原始模型评估
md_score1 = mode.score(x_test, y_test)  # 原模型准确率
auc_score1 = roc_auc_score(mode.predict(x_test), y_test)  # 原模型AUC值

# 6.调优模型
parameters = {
    'max_depth': [13, 14, 15],
    'min_samples_split': [13, 15, 17, 19, 21],
    'min_samples_leaf': [3, 4, 5, 6, 7],
    'criterion': ['gini', 'entropy']
}   # 选取常用调优超参数
mode1 = DecisionTreeClassifier(random_state=123)
grid_search = GridSearchCV(mode1, parameters, scoring='roc_auc', cv=5)
grid_search.fit(x_train, y_train)
best_params = grid_search.best_params_

# 7.根据调优参数重新定义模型
mode_new = DecisionTreeClassifier(
    max_depth=best_params['max_depth'],
    min_samples_split=best_params['min_samples_split'],
    min_samples_leaf=best_params['min_samples_leaf'],
    criterion=best_params['criterion'],
    random_state=123)
mode_new.fit(x_train, y_train)

# 8.对比原模型评估结果
md_score2 = mode_new.score(x_test, y_test)
print(f'调优后评估准确率变更: {round(md_score1*100, 2)}%-->{round(md_score2*100, 2)}%')
auc_score2 = roc_auc_score(mode_new.predict(x_test), y_test)
print(f'调优后AUC参数变更: {round(auc_score1*100, 2)}%-->{round(auc_score2*100, 2)}%')

# 9.调优后特征重要性变化
df_importance = pd.DataFrame()
df_importance['特征名称'] = x.columns
df_importance['特征重要性'] = mode_new.feature_importances_
print(df_importance.sort_values(by='特征重要性', ascending=False))

# 10.绘制模型ROC曲线
y_pre_proba = mode_new.predict_proba(x_test)
fpr, tpr, _ = roc_curve(y_test, y_pre_proba[:, 1])
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.plot(fpr, tpr)
plt.title('ROC曲线')
plt.xlabel('假报率-FPR')
plt.ylabel('命中率-TPR')
plt.show()
